package com.cbg.es.service.impl;

import com.cbg.enums.EsSearchManageExceptionEnum;
import com.cbg.enums.MoveDirectionEnum;
import com.cbg.es.dto.EsTableDTO;
import com.cbg.es.entity.EsTable;
import com.cbg.es.repository.IEsTableRepository;
import com.cbg.es.service.IEsColService;
import com.cbg.es.service.IEsTableService;
import com.cbg.es.vo.EsTableEditVO;
import com.cbg.es.vo.EsTableVO;
import com.cbg.utils.CollectionUtils;
import com.cbg.vo.StatusVO;
import com.shuyuwl.core.enums.StatusEnum;
import com.shuyuwl.core.exception.SymServiceException;
import com.shuyuwl.core.service.impl.DaoServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * ES表备份 serviceImpl
 *
 * @author wangjuzheng
 * @since 2019-10-16
 */
@Service
@Transactional(rollbackFor = SymServiceException.class)
public class EsTableServiceImpl extends DaoServiceImpl<EsTable, Long, IEsTableRepository> implements IEsTableService {

    @Resource
    private IEsTableRepository esTableRepository;

    @Resource
    private IEsColService esColService;

    @Override
    public List<EsTable> findAllEsTable(Byte status) {
        return esTableRepository.findByStatusOrderBySortAsc(status);
    }

    @Override
    public List<EsTableDTO> findAllEsTable() {

        List<EsTableDTO> esTableDTOs = new ArrayList<>();
        List<EsTable> esTables = esTableRepository.findByStatusLessThanOrderBySortAsc(StatusEnum.DELETE.getCode());
        if (CollectionUtils.isNotEmpty(esTables)) {
            return esTables.stream()
                    .sorted(Comparator.comparing(EsTable::getSort))
                    .map(esTable -> {
                        EsTableDTO esTableDTO = new EsTableDTO();
                        BeanUtils.copyProperties(esTable, esTableDTO);
                        return esTableDTO;
                    })
                    .collect(Collectors.toList());
        }
        return esTableDTOs;
    }

    @Override
    public void addTable(EsTableVO esTableVO) {

        EsTable esTable = new EsTable();
        EsTable repeatEsTable = checkRepeatTableNameAlias(esTableVO.getTableNameAlias());
        //表名已存在
        if (repeatEsTable != null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_TABLE_NAME_NOT_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_TABLE_NAME_NOT_NULL.getMsg());
        }
        BeanUtils.copyProperties(esTableVO, esTable);
        Integer sort = esTableRepository.getMaxSort(StatusEnum.DELETE.getCode());
        esTable.setSort(sort == null ? 1 : sort + 1);
        esTableRepository.save(esTable);
    }

    @Override
    public void deleteTable(List<Long> ids) {

        for (Long id : ids) {
            //参数验证
            EsTable esTable = checkEsTableAndStatusLessThan(id);

            //状态
            esTable.setStatus(StatusEnum.DELETE.getCode());
            //删除表下面的列
            esColService.deleteByTableName(esTable.getTableName());
            //删除表
            esTableRepository.save(esTable);
        }
    }

    @Override
    public void updateDirections(Long id, Integer directionType) {

        //参数验证
        EsTable esTable = checkEsTableAndStatusLessThan(id);
        List<EsTable> list = esTableRepository.findByStatusLessThanOrderBySortAsc(StatusEnum.DELETE.getCode());
        //表信息不存在
        if (CollectionUtils.isEmpty(list)) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_TABLE_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_TABLE_NULL.getMsg());
        }

        //获取需要移动类的下标
        int currentIndex = list.indexOf(esTable);
        if (currentIndex == -1) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_TABLE_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_TABLE_NULL.getMsg());
        }
        MoveDirectionEnum directionEnum = MoveDirectionEnum.getDirectionByCode(directionType);
        //请选择正确的移动方向
        if (directionEnum == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.MOVE_DIRECTION_NULL.getCode(), EsSearchManageExceptionEnum.MOVE_DIRECTION_NULL.getMsg());
        }

        moveCategoryDirections(currentIndex, esTable, directionEnum, list);
    }

    /**
     * 分类的位移
     *
     * @param currentIndex  移动类在所属分类下的下标
     * @param esTable       需要移动类信息
     * @param directionEnum 移动位置枚举
     * @param list          分类列表信息
     */
    private void moveCategoryDirections(int currentIndex, EsTable esTable, MoveDirectionEnum directionEnum, List<EsTable> list) {

        switch (directionEnum) {
            case UP:
                //上移，需要和前一个商品交换下标
                if (currentIndex == 0) {
                    //已经是第一个，无法上移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getMsg());
                }
                EsTable previous = list.get(currentIndex - 1);
                previous.setSort(previous.getSort() + 1);
                esTable.setSort(esTable.getSort() - 1);
                esTableRepository.save(previous);
                esTableRepository.save(esTable);
                break;
            case DOWN:
                //下移
                if (currentIndex == list.size() - 1) {
                    //已经是最后一个，无法下移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getMsg());
                }
                EsTable next = list.get(currentIndex + 1);
                next.setSort(next.getSort() - 1);
                esTable.setSort(currentIndex + 1);
                esTableRepository.save(next);
                esTableRepository.save(esTable);

                break;
            case TOP:
                //置顶
                if (currentIndex == 0) {
                    //已经是第一个，无法上移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getMsg());
                }
                esTable.setSort(list.get(0).getSort());
                esTableRepository.save(esTable);

                for (int i = 0; i < currentIndex; i++) {
                    EsTable newEsCategory = list.get(i);
                    newEsCategory.setSort(newEsCategory.getSort() + 1);
                    esTableRepository.save(newEsCategory);
                }
                break;
            case LAST:
                //置底
                if (currentIndex == list.size() - 1) {
                    //已经是第一个，无法上移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getMsg());
                }
                esTable.setSort(list.get(list.size() - 1).getSort());
                esTableRepository.save(esTable);

                for (int i = currentIndex + 1; i < list.size(); i++) {
                    EsTable newEsCategory = list.get(i);
                    newEsCategory.setSort(newEsCategory.getSort() - 1);
                    esTableRepository.save(newEsCategory);
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void saveTable(EsTableEditVO esTableEditVO) {

        //表信息的验证
        EsTable esTable = checkEsTableAndStatusLessThan(esTableEditVO.getId());
        //表名是否存在
        EsTable repeatEsTable = checkRepeatTableNameAlias(esTableEditVO.getTableNameAlias());
        //表名已存在
        if (repeatEsTable != null && !repeatEsTable.getId().equals(esTable.getId())) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_TABLE_NAME_NOT_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_TABLE_NAME_NOT_NULL.getMsg());
        }
        //表显示名
        esTable.setTableNameAlias(esTableEditVO.getTableNameAlias());
        //表显示名
        esTable.setStatus(esTableEditVO.getStatus());
        esTableRepository.save(esTable);
    }

    @Override
    public void updateStatus(StatusVO statusVO) {

        for (Long id : statusVO.getIds()) {
            checkEsTableAndStatusLessThan(id);
        }
        //表的更新
        esTableRepository.updateStatus(statusVO.getIds(), statusVO.getStatus());
    }

    @Override
    public EsTableDTO getDetails(Long id) {

        EsTable esTable = checkEsTableAndStatusLessThan(id);
        EsTableDTO esTableDTO = new EsTableDTO();
        BeanUtils.copyProperties(esTable, esTableDTO);
        return esTableDTO;
    }

    @Override
    public EsTable checkEsTable(Long id) {

        //表id不存在
        if (id == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_TABLE_ID_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_TABLE_ID_NULL.getMsg());
        }
        EsTable esTable = esTableRepository.findByIdAndStatus(id, StatusEnum.OK.getCode());
        //表信息不存在
        if (esTable == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_TABLE_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_TABLE_NULL.getMsg());
        }
        return esTable;
    }

    /**
     * 验证表是否存在
     *
     * @param tableId 表id
     * @return 表信息
     */
    public EsTable checkEsTableAndStatusLessThan(Long tableId) {

        //表id不存在
        if (tableId == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_TABLE_ID_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_TABLE_ID_NULL.getMsg());
        }
        EsTable esTable1 = esTableRepository.findByIdAndStatusLessThan(tableId, StatusEnum.DELETE.getCode());
        //表信息不存在
        if (esTable1 == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_TABLE_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_TABLE_NULL.getMsg());
        }
        return esTable1;
    }

    /**
     * 获取没有删除的表信息并排序
     *
     * @param tableNameAlias 显示名
     * @return 表信息
     */
    private EsTable checkRepeatTableNameAlias(String tableNameAlias) {
        return esTableRepository.findByTableNameAliasAndStatusLessThan(tableNameAlias.trim(), StatusEnum.DELETE.getCode());

    }
}
